package com.ivanceras.server.services;

import java.net.MalformedURLException;
import java.util.HashMap;

import com.google.gwt.user.server.rpc.RemoteServiceServlet;
import com.ivanceras.client.DataService;
import com.ivanceras.server.dao.DAO_Ad_tab;
import com.ivanceras.server.dao.DAO_Ad_table;
import com.ivanceras.server.dao.DAO_Ad_window;
import com.ivanceras.server.mapper.Ad_tabMapper;
import com.ivanceras.server.mapper.Ad_tableMapper;
import com.ivanceras.server.mapper.Ad_windowMapper;
import com.ivanceras.shared.bo.Ad_tab;
import com.ivanceras.shared.bo.Ad_table;
import com.ivanceras.shared.bo.Ad_window;
import com.ivanceras.shared.db.DAO;
import com.ivanceras.shared.db.EMF;
import com.ivanceras.shared.db.EntityManager;
import com.ivanceras.shared.db.Order;
import com.ivanceras.shared.db.SerializableDAO;
import com.ivanceras.shared.db.SerializableFilter;
import com.ivanceras.shared.exception.DatabaseException;
import com.ivanceras.shared.exception.IvancerasServiceException;


import java.util.Collections;
import net.sf.jsr107cache.Cache;
import net.sf.jsr107cache.CacheException;
import net.sf.jsr107cache.CacheFactory;
import net.sf.jsr107cache.CacheManager;

/**
 * The server side implementation of the RPC service.
 */
@SuppressWarnings("serial")
public class DataServiceImpl extends RemoteServiceServlet implements
DataService {

	@Override
	public Ad_window[] retrieveWindowList() throws IvancerasServiceException{
		EntityManager em = null;
		try {
			em = EMF.get();
			DAO_Ad_window[] daoWindowList = DataAPI.retrieveWindowList(em);
			System.out.println("windows: "+daoWindowList.length);
			return Ad_windowMapper.map(daoWindowList);
		} catch (DatabaseException e1) {
			e1.printStackTrace();
			throw new IvancerasServiceException();
		}
		finally{
			em.close();
		}
	}

	@Override
	public Ad_tab[] retriveTabList(Ad_window window) throws IvancerasServiceException {
		return retriveTabList(window, true);
	}
	public Ad_tab[] retriveTabList(Ad_window window, Boolean useCache) throws IvancerasServiceException {
	    Cache cache = null;
	    if(useCache){
	    	System.out.println("Using cache!");
	        try {
	            CacheFactory cacheFactory = CacheManager.getInstance().getCacheFactory();
	            cache = cacheFactory.createCache(Collections.emptyMap());
	            System.out.println("cache is: "+cache);
	            if(cache != null && cache.containsKey(window.getAd_window_uu())){
	            	System.err.println("cache hit! "+window.getName());
	            	return	(Ad_tab[])cache.get(window.getAd_window_uu());
	            }else if(cache == null){
	            	System.err.println("Cache is not available...");
	            }
	        } catch (CacheException e) {
            	System.err.println("Cache is not available...");
	        	e.printStackTrace();
	        }
		}
		EntityManager em = null;
		try {
			em = EMF.get();
			DAO_Ad_window daoWindow = new DAO_Ad_window();
			daoWindow.setAd_window_id(window.getAd_window_id());
			DAO_Ad_tab[] tabList = DataAPI.retriveTabList(em, daoWindow);
			Ad_tab[] adtabList = null;
			if(tabList != null){
				adtabList = Ad_tabMapper.map(tabList);
				if(useCache && cache != null){
					System.out.println("trying to put to cache: "+cache);
					System.out.println("This window: "+window);
					cache.put(window.getAd_window_uu(), adtabList);
				}
				return adtabList;
			}
			else{
				return null;
			}
		} catch (DatabaseException e1) {
			e1.printStackTrace();
			throw new IvancerasServiceException();
		}
		finally{
			em.close();
		}
	}

	@Override
	public SerializableDAO[] retrieveTableData(Ad_table table, Integer page, Integer itemPerPage,
			Order order, SerializableFilter sfilter) throws IvancerasServiceException {
		EntityManager em = null;
		try {
			em = EMF.get();
			DAO_Ad_table daoTable = Ad_tableMapper.map(table);
			DAO[] rdaoList = DataAPI.retrieveTableData(em, daoTable, page, itemPerPage, order, SerializableFilter.cast(sfilter));
			SerializableDAO[] daoList = SerializableDAO.cast(rdaoList);
			return daoList;
		} catch (DatabaseException e1) {
			e1.printStackTrace();
			throw new IvancerasServiceException();
		}
		finally{
			em.close();
		}
	}
	
	@Override
	public Boolean importDaoXmlFromUrl(String httpurl) throws IvancerasServiceException{
		EntityManager em = null;
		try {
			em = EMF.get();
			DataAPI.importDAO(em, httpurl);
			return true;
		} catch (DatabaseException e) {
			e.printStackTrace();
			throw new IvancerasServiceException("SQL exception");
		} catch (MalformedURLException e) {
			e.printStackTrace();
			throw new IvancerasServiceException("XML is malformed");
		}
		finally{
			em.close();
		}
	}
	
	@Override
	public HashMap<String, Integer> getTableList(String xmlurl) throws IvancerasServiceException{
		try {
			return DataAPI.parseTableListXml(xmlurl);
		} catch (MalformedURLException e) {
			e.printStackTrace();
			throw new IvancerasServiceException("XML is malformed");
		}
	}
	
	public Boolean saveDao(SerializableDAO[] s_daoList) throws IvancerasServiceException{
		EntityManager em = null;
		try {
			em = EMF.get();
			DataAPI.saveDao(em, SerializableDAO.cast(s_daoList));
			return true;
		} catch (DatabaseException e1) {
			e1.printStackTrace();
			throw new IvancerasServiceException();
		}
		finally{
			em.close();
		}
		
	}

}
